Solutions/Threat Intelligence (NEW)/Analytic Rules/imDns_DomainEntity_DnsEvents.yaml (83 lines of code) (raw):

id: 7c1ea2e6-6210-412c-92e4-180803a741b4 name: TI map Domain entity to Dns Events (ASIM DNS Schema) description: | Identifies a match in DNS events from any Domain IOC from TI This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM DNS schema' severity: Medium requiredDataConnectors: - connectorId: ThreatIntelligence dataTypes: - ThreatIntelligenceIndicator - connectorId: ThreatIntelligenceTaxii dataTypes: - ThreatIntelligenceIndicator - connectorId: DNS dataTypes: - DnsEvents - connectorId: AzureFirewall dataTypes: - AzureDiagnostics - connectorId: Zscaler dataTypes: - CommonSecurityLog - connectorId: InfobloxNIOS dataTypes: - Syslog - connectorId: GCPDNSDataConnector dataTypes: - GCP_DNS_CL - connectorId: NXLogDnsLogs dataTypes: - NXLog_DNS_Server_CL - connectorId: MicrosoftDefenderThreatIntelligence dataTypes: - ThreatIntelligenceIndicator - connectorId: CiscoUmbrellaDataConnector dataTypes: - Cisco_Umbrella_dns_CL - connectorId: Corelight dataTypes: - Corelight_CL queryFrequency: 1h queryPeriod: 14d triggerOperator: gt triggerThreshold: 0 tactics: - CommandAndControl relevantTechniques: - T1071 tags: - Id: 85aca4d1-5d15-4001-abd9-acb86ca1786a version: 1.0.0 - Schema: ASIMDns SchemaVersion: 0.1.1 query: | let HAS_ANY_MAX = 10000; let dt_lookBack = 1h; let ioc_lookBack = 14d; let DomainTIs= ThreatIntelIndicators // Picking up only IOC's that contain the entities we want //extract key part of kv pair | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0))) | where isnotempty(IndicatorType) and IndicatorType == "domain-name" | extend DomainName = ObservableValue | extend Url = iff(ObservableKey == "url:value", ObservableValue, "") | where isnotempty(DomainName) | extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel) | extend ThreatList = tostring(parse_json(Data).indicator_types[0]) | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id | where IsActive == true and ValidUntil > now(); let Domains = DomainTIs | where isnotempty(DomainName) |summarize NDomains=dcount(DomainName), DomainsList=make_set(DomainName) | project DomainList = iff(NDomains > HAS_ANY_MAX, dynamic([]), DomainsList); DomainTIs | project-reorder *, ThreatList, IsActive, Tags, TrafficLightProtocolLevel, DomainName, Type | join ( _Im_Dns(starttime=ago(dt_lookBack), domain_has_any=toscalar(Domains)) | extend DNS_TimeGenerated = TimeGenerated ) on $left.DomainName==$right.DnsQuery | where DNS_TimeGenerated < ValidUntil | extend Description = tostring(parse_json(Data).description) | extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(parse_json(Data).labels)) | project LatestIndicatorTime, Description, ActivityGroupNames, Id, ValidUntil, Confidence, DNS_TimeGenerated, Dvc, SrcIpAddr, Domain, DnsQuery, DnsQueryType, Url | extend HostName = tostring(split(Dvc, ".")[0]), DomainIndex = toint(indexof(Dvc, '.')) | extend HostNameDomain = iff(DomainIndex != -1, substring(Dvc, DomainIndex + 1), Dvc) entityMappings: - entityType: Host fieldMappings: - identifier: FullName columnName: Dvc - identifier: HostName columnName: HostName - identifier: DnsDomain columnName: HostNameDomain - entityType: IP fieldMappings: - identifier: Address columnName: SrcIpAddr - entityType: URL fieldMappings: - identifier: Url columnName: Url - entityType: DNS fieldMappings: - identifier: DomainName columnName: Domain customDetails: LatestIndicatorTime: LatestIndicatorTime Description: Description ActivityGroupNames: ActivityGroupNames IndicatorId: IndicatorId ThreatType: ThreatType ExpirationDateTime: ExpirationDateTime ConfidenceScore: Confidence DNSRequestTime: DNS_TimeGenerated SourceIPAddress: SrcIpAddr DnsQuery: DnsQuery QueryType: DnsQueryType version: 1.2.0 kind: Scheduled